// by Jens Schmidt 2009
// for: YOU
// use, modify, copy this as you like

function MainAssistant() {
	// settings and status variables
	this.settings = new Settings();
	this.comms = new  LocrComms();
	this.tempPass=0;
	this.filename=0;
	this.state='init';
	this.gpsIdle=true;
	this.netStateRegistered=false;
	this.netConnected=true;
	this.foreground=true;
	
	// bindings
	this.getPosFn=this.gotPos.bind(this);
	this.noPosFn=this.noPos.bind(this);
	this.selPicFn=this.PictureSelected.bind(this);
	this.CameraFn=this.takePhoto.bind(this);
	this.photoListFn=this.selectPhoto.bind(this);
	this.commsCallbackFn=this.locrCallback.bind(this);
}

MainAssistant.prototype.handleCommand = function(event) {
	if  (event.type== Mojo.Event.command && event.command == 'do-myPrefs') {
		// preferences called from the menu
		this.state = 'setPrefs';
		this.controller.stageController.pushScene("preferences", this.settings);
	}
}

MainAssistant.prototype.activateWindow = function(event) {
	// we stopped spinners when we went to background
	// restart them here if required
	this.foreground=true;
	if (this.comms && this.comms.busy){
		this.scrimSpinner.mojo.start();
	}else if (!this.gpsIdle){
		this.gpsSpinnerWidget.mojo.start();
	}
};

MainAssistant.prototype.deactivateWindow = function(event) {
	// do the battery a fvour
	// stop spinners when in background
	this.foreground=false;
	this.stateSpinner.mojo.stop();
	if (!this.gpsIdle){
		this.gpsSpinnerWidget.mojo.stop();
	}
	if (this.comms && this.comms.busy){
		this.scrimSpinner.mojo.stop();
	}
};

MainAssistant.prototype.setup = function() {
	
	// set scene wide variables (for faster access to UI elements)
	this.positionTextField=this.controller.get("Position");
	this.accountNameTextField=this.controller.get("Account");
	this.statusTextField=this.controller.get("Status");
	this.gpsSpinnerWidget=this.controller.get("gpsSpinner");
	this.scrimWidget=this.controller.get("scrim");	
	this.scrimSpinner=this.controller.get("spinner");
	this.stateSpinner=this.controller.get("stateSpinner");
	this.photoWidget=this.controller.get("Photos");

	// listen for taps on the position text
	Mojo.Event.listen(this.positionTextField, Mojo.Event.tap, this.updatePos.bind(this));

	// set the menu
	this.controller.setupWidget(Mojo.Menu.appMenu,
       this.attributes = {
                omitDefaultItems: true
            },
    	this.model = {
        	visible: true,
        	items: [ 
                { label: "Preferences...", command: 'do-myPrefs' },
        	]
    });
	
	// spinners
	this.controller.setupWidget("spinner",
         this.attributes = {
             spinnerSize: 'large'
         },
         this.model = {
             spinning: false 
         });

	this.controller.setupWidget("gpsSpinner",
         this.attributes = {
             spinnerSize: 'small'
         },
         this.model = {
             spinning: false 
         });

	this.controller.setupWidget("stateSpinner",
         this.attributes = {
             spinnerSize: 'small'
         },
         this.model = {
             spinning: false 
         });

	// buttons
	this.controller.setupWidget("Photos",
        this.attributes = {
			choices: [{
				label: "Take Photo",
				value: 1
			}, {
				label: "Select Photo",
				value: 2
			}, ]
		},

        this.model = {
        value: 0,
        disabled: false
    });
	Mojo.Event.listen(this.photoWidget, Mojo.Event.propertyChange, this.tapPhotos.bind(this));
	
	this.controller.setupWidget("UploadQueue", this.buttonAttributes,
		{"label" : "UploadQueue...",
 		"buttonClass" : 'secondary',
    	"disabled" : false
   		}
	);
    Mojo.Event.listen(this.controller.get("UploadQueue"), Mojo.Event.tap, this.queue.bind(this));	
	
	// finally, observe foreground/background
	Mojo.Event.listen(this.controller.stageController.document, Mojo.Event.stageActivate, 
		this.activateWindow.bind(this));

	Mojo.Event.listen(this.controller.stageController.document, Mojo.Event.stageDeactivate, 
		this.deactivateWindow.bind(this));
		
	this.positionTextField.update('<b>Position:</b> (tap here to update)');
}

MainAssistant.prototype.queue = function(){
	this.state = 'handlequeue';
	this.controller.stageController.pushScene("queue");
}

MainAssistant.prototype.updatePos=function(){
	if (this.gpsIdle) {
		this.gpsIdle = false;
		this.controller.serviceRequest('palm://com.palm.location', {
			method: 'getCurrentPosition',
			parameters: {
				'accuracy': 1
			},
			onSuccess: this.getPosFn,
			onFailure: this.noPosFn,
		});
		this.gpsSpinnerWidget.mojo.start();
		this.positionTextField.update('<b>Position:</b>' + ' obtaining...');
	}
}

MainAssistant.prototype.gotPos = function(resp){
	// position (GPS) request terminated
	this.gpsIdle=true;
	this.gpsSpinnerWidget.mojo.stop();
	if (resp.errorCode==0){
		// got a position - show it
		this.positionTextField.update('<b>Position:</b> (tap here to update)'+
			'<br />Lat: ' +	resp.latitude +
			'<br />Long: ' + resp.longitude);	
	}else{
		// apparently no position could be obtained
		noPos(resp);
	}
}

MainAssistant.prototype.noPos = function(resp){
	// alert the user that we cannot obtain GPS/positioning information
	this.gpsIdle=true;
	this.gpsSpinnerWidget.mojo.stop();
	this.positionTextField.update('<b>Position:</b> (tap here to update)'+'<br />not available<br />Are location based services activated?');
	// debug only: :<br />'+Object.toJSON(resp));
}

MainAssistant.prototype.gotNetState = function(resp){
	// network status changed
	this.netStateRegistered=true;
	this.netConnected=resp.isInternetConnectionAvailable;
}

MainAssistant.prototype.dbCallback = function(state){
	if (state && state != 'fail' && this.uploadQueue && this.uploadQueue.list.length > 0) {
		//this.uploadQueue.list;
		var element=this.uploadQueue.list[0];
//		this.statusTextField.update('<b>Status:</b> uploading \"' + element.shownName+'\"');
		this.filename=element.filename;
		this.state='handleDetails';
		this.activate({
			'action':'send',
			'caption':element.caption,
			'description':element.description,
			'privacy':element.privacy,
			});
	}
	else {
		// done
		this.state='init';
		this.uploadQueue = 0;
		this.statusTextField.update('<b>Status:</b> ready');
	}
}

MainAssistant.prototype.activate = function(params) {
	// we came to top
	
	// always trigger a position update
	//this.updatePos();
	if (!this.gpsIdle) {
		this.gpsSpinnerWidget.mojo.start();
	}
	
	if (this.comms && this.comms.busy){
		this.gpsSpinnerWidget.mojo.stop();
	}else{
		this.scrimSpinner.mojo.stop();
		this.scrimWidget.hide();
	}

	// the state spinner is shown, when image selector or camera are launched
	// because those take some time
	// safe to remove it when we're on top again
	this.stateSpinner.mojo.stop();
	this.controller.setWidgetModel( this.photoWidget,{value: 0, disabled: false});
	
	if (!this.netStateRegistered) {
		// subscribe (once) for network status updates
		this.controller.serviceRequest('palm://com.palm.connectionmanager', {
			method: 'getstatus',
			parameters: {subscribe:true},
			onSuccess: this.gotNetState.bind(this)
		});
	}

	// display account name (if set)
	if (this.settings && this.settings.Name && this.settings.Name.length>0){
		// account name is set (in the prefs)
		this.accountNameTextField.update('<b>Account:</b> '+this.settings.Name);
	}
	else{
		// account name is not set in the prefs
		this.accountNameTextField.update('<b>Account:</b> '+'not set (see Preferences)');
	}
	
	switch (this.state){
		case 'handlequeue':
			if (params && params.action == 'uploadAll') {
				this.uploadQueue = new UploadQueue(this.dbCallback.bind(this));
				this.statusTextField.update('<b>Status:</b> '+'uploading queue');
			}else{
				this.state='init';
				this.statusTextField.update('<b>Status:</b> '+'ready');	
			}
			break;
			
		case 'setPrefs':
			// coming from the prefs scene (which was opened by the user)
			if (this.settings.Name && this.settings.Pass && this.netConnected) {
				// username and password stored in the prefs / check if they are OK
				this.tempPass=0; // pw now in the prefs, can delete tmp pw if one existed
				this.statusTextField.update('<b>Status:</b> '+'checking login');
				if (!this.gpsIdle){
					this.gpsSpinnerWidget.mojo.stop();
				}
				this.scrimSpinner.mojo.start();
				this.scrimWidget.show();
				this.comms.getLocr({
					what: LocrComms.validateLogin,
					username: this.settings.Name,
					pass: this.settings.Pass,
					callback: this.commsCallbackFn
				});
				return;
			}else{
				this.state='init';
			}
			// fall through
		
		case 'init':
			// excellent, show the user we're ready
			this.statusTextField.update('<b>Status:</b> '+'ready');
			break;
		
		case 'takingPhoto':
			if (params && params.returnValue && params.filename) {
				//if the user took a photo, store the filename
				this.filename = params.filename;
				//this.statusTextField.update(Object.toJSON(params));
			}
			// fall through

		case 'selectPicture':
			if (this.filename && (this.filename.substring(this.filename.length-4)!='.jpg')){
					Mojo.Controller.errorDialog('Only .jpg files can be uploaded to Locr.')
					this.filename=0;
			}
			if (!this.filename){
				// not photo taken or no photo selected - fine
				this.state = 'init';
				this.statusTextField.update('<b>Status:</b> '+'ready');
			}else{
				// photo take or selected from storage
				// let the user set the details
				this.controller.stageController.pushScene("image-details",{
					'filename': this.filename
				});
				this.state = 'handleDetails';
			}
			break;
			
		case 'handleDetails':
			if (!(params && params.action=='send')){
				// user left the details scene without triggering upload
				// fine with us
				this.statusTextField.update('<b>Status:</b> '+'ready');
				this.state = 'init';
				return;
			}
			
			if (!this.netConnected)
			{
				this.controller.showAlertDialog({
    				title: $L("No InternetConnection"),
    				message: $L("The phone is currently not connected to the internet. Try again later."),
    				choices:[
         				{label:$L("Nevermind"), value:"cancel", type:'dismiss'}    
    					]
    			});
				this.uploadQueue=0;
				this.state = 'init';
				this.statusTextField.update('<b>Status:</b> '+'cancelled');
				return;
			}	
			
			// user set a photos details and triggered upload
			// we store the details (and move on below)
			this.caption=params.caption;
			this.description=params.description;
			this.privacy=params.privacy;
			
			if (!this.settings.Name){
				// attempt to upload with no account name being set
				// automatically launch preferences scene
				this.state = 'setaccount';
				this.controller.stageController.pushScene("preferences", this.settings);
				return;
			}
			// otherwise: fine, fall through
			
		case 'setaccount':
			if (!this.settings.Name){
				// we can only get here if the account name was not set
				// and in the subsequently launched preferences scene
				// there was still no account name set - consider this a "cancel"
				this.uploadQueue=0;
				this.statusTextField.update('<b>Status:</b> '+'cancelled');
				this.state = 'init';
				return;
			}
			
			if (this.state=='setaccount'){
				// account name was just set in the automatically launched prefs scene
				// update display in this scene
				this.accountNameTextField.update('<b>Account:</b> '+this.settings.Name);
			}
			// if we got here: we have an upload pending and the account name is set
			// fall through
					
		case 'getpassword':				
			if (this.state=='getpassword' && params) {
				// the password is not stored in the preferences
				// it was just set by the user in the temp password scene
				this.tempPass = params;
			}
		
			if ((!(this.settings.Pass || this.tempPass))
				|| (this.settings.Pass.length==0 && this.tempPass.length==0)){
				// no password in the preferences and no temporary password
				if (this.uploadQueue) {
					Mojo.Controller.errorDialog('For queued uploads the password must be stored in the preferences');
					this.uploadQueue = 0;
					this.statusTextField.update('<b>Status:</b> ' + 'cancelled');
					this.state = 'init';
				}else if (this.state == 'getpassword') {
					// just coming from the temp password scene
					// user didn't enter the password
					this.statusTextField.update('<b>Status:</b> '+'cancelled');
					this.state = 'init';
				}
				else {
					// launch the scene to ask for temporary password
					this.state = 'getpassword';
					this.controller.stageController.pushScene("password");
				}
				// anyway, we cannot continue with the upload without password
				return;
			}

			// here we are, having the filename, user name and password
			// attempt to upload
			
			if (!this.uploadQueue) {
				this.statusTextField.update('<b>Status:</b> ' + 'uploading');
			}
			if (!this.gpsIdle){
				this.gpsSpinnerWidget.mojo.stop();
			}
			this.scrimSpinner.mojo.start();
			this.scrimWidget.show();
			var pass;
			if (this.settings.Pass){
				pass=this.settings.Pass;
			}else{
				pass=this.tempPass;
			}
			this.comms.getLocr({
					what: LocrComms.uploadCommand,
					username: this.settings.Name,
					pass: pass,
					filename: this.filename,
					caption: this.caption,
					description: this.description,
					privacy: this.privacy,
					callback: this.commsCallbackFn
				});
			this.filename=0; // no longer required;
			break;
			
 	  	default:
	  		this.statusTextField.update('<b>Status:</b> '+this.state);
	  }
}


MainAssistant.prototype.deactivate = function(event) {
}

MainAssistant.prototype.cleanup = function(event) {
	// ??? Mojo.Event.stopListening(); 
}

MainAssistant.prototype.PictureSelected = function (name) {
	// user selected a picture from the list - store filename
	this.filename=name.fullPath;
}

MainAssistant.prototype.tapPhotos = function(event){
	if (!this.gpsIdle) {
		// don't want to confuse the user with two spinners
		this.gpsSpinnerWidget.mojo.stop();
	}
	this.stateSpinner.mojo.start();
		switch(event.model.value){
		case 1:
			this.statusTextField.update('<b>Status:</b> '+'starting camera...');
			this.CameraFn();
			break;

		case 2:
			this.statusTextField.update('<b>Status:</b> '+'loading photos...');
			this.photoListFn();
			break;
	}
}

MainAssistant.prototype.selectPhoto = function(event){
	if (this.state == 'init') {
		this.filename=0;
		this.state = 'selectPicture';
		var params = {
			'onSelect': this.selPicFn,
			'kinds': ['image'],
			'actionName': 'Select'
		};
		Mojo.FilePicker.pickFile(params, this.controller.stageController);
	}
	else{
		this.statusTextField.update('<b>Status:</b> '+'busy - try again later');
	}
}

MainAssistant.prototype.takePhoto = function(event){
	if (this.state == 'init') {
		this.filename=0;
		this.state='takingPhoto';
		this.controller.stageController.pushScene({
			appId: 'com.palm.app.camera',
			name: 'capture'
		}, {
			sublaunch: true
		});
	}
	else{
		this.statusTextField.update('<b>Status:</b> '+'busy - try again later');
	}
}

MainAssistant.prototype.locrCallback = function(params){
	if (params.type==LocrComms.notificationType){
/*		if (params.transport) {
			this.statusTextField.update('<b>Status:</b> ' + params.txt+'<br />'
			+Object.toJSON(params.transport));
		}
		else {
*/			this.statusTextField.update('<b>Status:</b> ' + params.txt);
//		}
		if (params.finished){
			if ((!this.uploadQueue) || this.uploadQueue.list.length <= 1) {
				// nothing more to upload
				if (this.foreground) {
					if (!this.gpsIdle) {
						this.gpsSpinnerWidget.mojo.start();
					}
				}
				else {
					Mojo.Controller.getAppController().showBanner('LocrUploader: ' + params.txt, {
						source: ''
					});
				}
				this.scrimSpinner.mojo.stop();
				this.scrimWidget.hide();
				this.state = 'init';
			}
			
			if (this.uploadQueue){
				if (this.uploadQueue.list.length>0){
					var msg=this.uploadQueue.deleteElement(0);
					/*
					 this.statusTextField.update('<b>Status:</b> still to upload '
						+this.uploadQueue.list.length+'<br />'+
						Object.toJSON(msg));
					*/
				}
				else{
					this.uploadQueue==0;
				}
			}
		}	
	}else if(params.type==LocrComms.notificationTypeUploadForMe && params.param) {
			// comms module cannot call the download manager
			// so we do it here:
			this.controller.serviceRequest('palm://com.palm.downloadmanager/', params.param);
	}
}